package org.chen.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.chen.mapper.news.CommentRuleMapper;
import org.chen.mapper.news.CommentTaskMapper;
import org.chen.mapper.old.OldCommentRuleMapper;
import org.chen.mapper.old.OldCommentTaskMapper;
import org.chen.model.CommentRule;
import org.chen.model.CommentTask;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class CommentRuleMigrationService {

    @Autowired
    private OldCommentRuleMapper oldTaskMapper; // 原表的Mapper
    
    @Autowired
    private CommentRuleMapper newTaskMapper; // 新表的Mapper
    
    @Value("${migration.batch-size:1000}")
    private int batchSize;

    /**
     * 迁移数据
     */
    public void migrateRule() {
        try {
            // 先检查总数
            Long totalCount = oldTaskMapper.selectCount(null);
            log.info("原表数据总量: {}", totalCount);

            // 使用分页查询替代
            Page<CommentRule> page = new Page<>(1, batchSize);
            while (true) {
                // 使用MyBatis-Plus的分页查询
                IPage<CommentRule> pageResult = oldTaskMapper.selectPage(page,
                        new QueryWrapper<CommentRule>().orderByAsc("id"));

                if (pageResult.getRecords().isEmpty()) {
                    break;
                }

                log.info("处理第{}页数据, 数量: {}", page.getCurrent(),
                        pageResult.getRecords().size());

                // 转换并插入数据
                List<CommentRule> oldTasks = pageResult.getRecords();
                convertAndInsertBatch(oldTasks);

                if (page.getCurrent() >= pageResult.getPages()) {
                    break;
                }

                page.setCurrent(page.getCurrent() + 1);
            }

        } catch (Exception e) {
            log.error("数据迁移失败", e);
            throw new RuntimeException("数据迁移失败", e);
        }
    }

    private void convertAndInsertBatch(List<CommentRule> oldTasks) {
        Map<Integer, List<CommentRule>> shardingGroups = new HashMap<>();

        for (CommentRule oldTask : oldTasks) {
            CommentRule newTask = convertToNewTask(oldTask);
            int shardingKey = Math.toIntExact(newTask.getId() % 11);
            log.info("任务ID: {}, 分片键: {}", newTask.getId(), shardingKey);
            shardingGroups.computeIfAbsent(shardingKey, k -> new ArrayList<>())
                    .add(newTask);
        }

        for (Map.Entry<Integer, List<CommentRule>> entry : shardingGroups.entrySet()) {
            try {
                int shardingKey = entry.getKey();
                List<CommentRule> tasks = entry.getValue();
                log.info("正在插入分片{}, 数据量: {}", shardingKey, tasks.size());
                newTaskMapper.batchInsert(tasks);
                // 验证插入
                for (CommentRule task : tasks) {
                    CommentRule inserted = newTaskMapper.selectById(task.getId());
                    if (inserted == null) {
                        log.error("分片{}中的任务{}插入失败", shardingKey, task.getId());
                    }
                }
            } catch (Exception e) {
                log.error("分片{}插入失败: {}", entry.getKey(), e.getMessage(), e);
                throw new RuntimeException("数据迁移失败", e);
            }
        }
    }

    /**
     * 转换为新的任务对象
     */
    private CommentRule convertToNewTask(CommentRule oldTask) {
        CommentRule newTask = new CommentRule();
        // 生成新的雪花ID
        newTask.setId(IdWorker.getId());
        // 复制其他属性
        BeanUtils.copyProperties(oldTask, newTask, "id");
        return newTask;
    }

    /**
     * 验证迁移数据
     */
    public void validateMigrationRule() {
        try {
            log.info("开始验证数据迁移...");

            // 检查数据总量
            long oldCount = oldTaskMapper.selectCount(null);
            long newCount = newTaskMapper.selectCount(null);
            
            log.info("原表数据量: {}, 新表数据量: {}", oldCount, newCount);
            
            if (oldCount != newCount) {
                log.error("数据量不一致！");
                return;
            }

            // 抽样验证数据内容
            validateSampleData();
            
            log.info("数据迁移验证完成");
            
        } catch (Exception e) {
            log.error("数据迁移验证失败", e);
        }
    }

    /**
     * 抽样验证数据
     */
    private void validateSampleData() {
        // 随机抽取一些数据进行验证
        List<CommentRule> sampleOldTasks = oldTaskMapper.selectRandomSample(100);
        
        for (CommentRule oldTask : sampleOldTasks) {
            // 通过批次号和目标URL等唯一标识查找新数据
            CommentRule newTask = newTaskMapper.selectByUrl(
                oldTask.getUrlPattern()
            );
            
            if (newTask == null) {
                log.error("数据丢失: id={}, urlPattern={}",
                    oldTask.getId(), oldTask.getUrlPattern());
                continue;
            }

            // 验证数据一致性
            validateTaskData(oldTask, newTask);
        }
    }

    /**
     * 验证任务数据一致性
     */
    private void validateTaskData(CommentRule oldTask, CommentRule newTask) {
        if (!Objects.equals(oldTask.getUrlPattern(), newTask.getUrlPattern()) ||
            !Objects.equals(oldTask.getUseCount(), newTask.getUseCount())) {
            
            log.error("数据不一致: oldId={}, newId={}", oldTask.getId(), newTask.getId());
        }
    }
}